﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using System.ServiceModel;
using System.Threading;

using Faust.Andrew.MTG.Helper;

namespace Faust.Andrew.MTG.Player
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window, IMainView
    {

        static MainWindow()
        {
            PresenterProperty = DependencyProperty.Register("Presenter", typeof(GamePresenter), typeof(MainWindow));
        }

        static DependencyProperty PresenterProperty;
        public GamePresenter Presenter
        {
            get
            {
                return (GamePresenter)base.GetValue(PresenterProperty);
            }
            set
            {
                base.SetValue(PresenterProperty, value);
            }
        }

        #region fields
        //private GamePresenter Presenter { get; set; }
        private bool _commandLineMode = false;
        private string _commandLineName = String.Empty;
        private int _commandLinePort = 0;
        private string _commandLineHost = String.Empty;
        private string _commandLineDeck = String.Empty;
        private bool _commandLineIsHost = false;
                      
        #endregion

        #region Constructors
        public MainWindow()
        {
            InitializeComponent();
            Presenter = new GamePresenter();
            Presenter.SetView(this);
            Presenter.SetView(playSurface);
            //Presenter.SetView((IPlayersView)playersInfo);
            
            handHost.Content = Presenter.CreateHandView();
            handHost.Title = "Hand";
            DockSetting setting = LoadLayout(handHost);
            Presenter.SetHandZoom(setting.Zoom);

            workspaceHost.Content = Presenter.CreateWorkspaceView();
            workspaceHost.Title = "Workspace";
            setting = LoadLayout(workspaceHost);
            Presenter.SetWorkspaceZoom(setting.Zoom);

            previewHost.Content = Presenter.CreatePreviewView();
            previewHost.Title = "Card Preview";
            LoadLayout(previewHost);

            controlsHost.Content = Presenter.CreateControlsView();
            controlsHost.Title = "Controls";
            LoadLayout(controlsHost);

            notificationsHost.Content = Presenter.CreateNotificationsView();
            notificationsHost.Title = "Messages";
            LoadLayout(notificationsHost);

            playersHost.Content = Presenter.CreatePlayersView();
            playersHost.Title = "Players";
            LoadLayout(playersHost);

            planeHost.Content = Presenter.CreatePlanesView();
            planeHost.Title = "Plane";
            LoadLayout(planeHost);

            LoadWindowLayout();

            //playersInfo.Presenter = Presenter;
            playSurface.Presenter = Presenter;
        }

        protected void SaveLayout()
        {
            SaveLayout(handHost, Presenter.GetHandZoom());
            SaveLayout(workspaceHost, Presenter.GetWorkspaceZoom());
            SaveLayout(previewHost);
            SaveLayout(controlsHost);
            SaveLayout(notificationsHost);
            SaveLayout(playersHost);
            SaveLayout(planeHost);

            SaveWindowLayout();            
        }

        public void SaveWindowLayout()
        {
            WindowSettings windowSettings = new WindowSettings()
            {
                IsWindowMaximized = (this.WindowState == WindowState.Maximized),
                WindowHeight = this.Height,
                WindowWidth = this.Width
            };

            string path = String.Format("{0}\\DockSettings.xml", Presenter.Model.UserDirectory);
            DockSettingManager manager = new DockSettingManager(path);
            manager.WriteWindowSettings(windowSettings);
        }

        private void SaveLayout(DockablePanel panel)
        {
            SaveLayout(panel, 1.0);
        }

        private void SaveLayout(DockablePanel panel, double zoom)
        {            
            DockSetting setting = new DockSetting()
            {
                Height = panel.Height,
                Width = panel.Width,
                Top = Canvas.GetTop(panel),
                Left = Canvas.GetLeft(panel),
                Name = panel.Title,
                Zoom = zoom
            };

            string path = String.Format("{0}\\DockSettings.xml", Presenter.Model.UserDirectory);
            DockSettingManager manager = new DockSettingManager(path);
            manager.WriteSetting(setting);
        }

        public void LoadWindowLayout()
        {
            string path = String.Format("{0}\\DockSettings.xml", Presenter.Model.UserDirectory);
            DockSettingManager manager = new DockSettingManager(path);
            WindowSettings settings = manager.ReadWindowSettings();

            if (settings != null)
            {
                if (settings.IsWindowMaximized)
                {
                    this.WindowState = WindowState.Maximized;
                }
                else
                {
                    this.WindowState = WindowState.Normal;
                    this.Height = settings.WindowHeight;
                    this.Width = settings.WindowWidth;
                }
            }
        }

        private DockSetting LoadLayout(DockablePanel panel)
        {
            string path = String.Format("{0}\\DockSettings.xml", Presenter.Model.UserDirectory);
            DockSettingManager manager = new DockSettingManager(path);
            DockSetting setting = manager.ReadSetting(panel.Title);

            if (setting != null)
            {
                Canvas.SetTop(panel, setting.Top);
                Canvas.SetLeft(panel, setting.Left);
                panel.Width = setting.Width;
                panel.Height = setting.Height;
            }
            else
            {
                setting = new DockSetting();
            }

            return setting;
        }

        public MainWindow(bool isHost, string host, int port, string name, string deck) : this()
        {
            _commandLineMode = true;
            _commandLineIsHost = isHost;
            _commandLineDeck = deck;
            _commandLinePort = port;
            _commandLineName = name;
            _commandLineHost = host;
        }

        private void Window_Loaded(object sender, System.Windows.RoutedEventArgs e)
        {
            if (_commandLineMode)
            {
                if (_commandLineIsHost)
                {
                    Presenter.Model.HostGame();
                }
                else
                {
                    Presenter.Model.JoinGame();
                }
            }
        }
        #endregion

        #region Menus                
        private void mnuHostGame_Click(object sender, System.Windows.RoutedEventArgs e)
        {
            Presenter.Model.HostGame();
        }

        private void mnuStartGame_Click(object sender, System.Windows.RoutedEventArgs e)
        {
            Presenter.Model.StartGame();
        }        

        private void mnuJoinGame_Click(object sender, System.Windows.RoutedEventArgs e)
        {
            Presenter.Model.JoinGame();            
        }

        private void mnuExit_Click(object sender, System.Windows.RoutedEventArgs e)
        {
			Presenter.Model.EndGame();
            Application.Current.Shutdown();
        }

        private void mnuEndGame_Click(object sender, System.Windows.RoutedEventArgs e)
        {
            Presenter.Model.EndGame();
        }

        #endregion

        #region IMainView Callbacks
        public void StartingGameLoading()
        {
            spLoading.Visibility = Visibility.Visible;
        }

        public void ReportGameLoading(int cardNumber, int totalCards)
        {
            if (totalCards < cardNumber || cardNumber < 0 )
            {
                pbLoading.IsIndeterminate = true;
            }
            else
            {
                pbLoading.IsIndeterminate = false;
                pbLoading.Maximum = totalCards;
                pbLoading.Value = cardNumber;
            }

            Application.Current.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Background, new ThreadStart(delegate { }));
            
        }

        public void FinishedGameLoading()
        {
            spLoading.Visibility = Visibility.Collapsed;
        }

        public void ReportError(string message)
        {
            MessageBox.Show(message);    
        }

        public double GetZoomLevel()
        {
            return zoomControl.Zoom;
        }

        public bool GetHostParameters(List<string> decks, ref string name, ref int port, ref string deckName, ref bool usePlanes)
        {
            if (_commandLineMode)
            {
                name = _commandLineName;
                port = _commandLinePort;
                deckName = _commandLineDeck;
                usePlanes = true;
                Title = "Host MTG Player - " + name;
                return true;
            }

            HostGameConfigurationWindow hostConfiguration = new HostGameConfigurationWindow();
            hostConfiguration.Decks = decks;
            if (hostConfiguration.ShowDialog() == true)
            {
                name = hostConfiguration.Name;
                port = hostConfiguration.Port;
                deckName = hostConfiguration.DeckName;
                usePlanes = hostConfiguration.UsePlanes;
                Title = "MTG Player - " + name;
                return true;
            }
            else
            {
                return false;
            }
        }

        public bool GetJoinParameters(List<string> decks, ref string name, ref string host, ref int port, ref string deckName, ref bool isRejoin)
        {
            if (_commandLineMode)
            {
                name = _commandLineName;
                port = _commandLinePort;
                deckName = _commandLineDeck;
                host = _commandLineHost;
                isRejoin = false;
                Title = "Guest MTG Player - " + name;
                return true;
            }

            JoinGameConfigurationWindow joinConfiguration = new JoinGameConfigurationWindow();
            joinConfiguration.Decks = decks;
            if (joinConfiguration.ShowDialog() == true)
            {
                name = joinConfiguration.Name;
                host = joinConfiguration.Host;
                port = joinConfiguration.Port;
                deckName = joinConfiguration.DeckName;
                isRejoin = joinConfiguration.IsRejoin;
                Title = "MTG Player - " + name;
                
                return true;
            }
            else
            {
                return false;
            }
        }

        public int GetTargetPlayer()
        {
            TargetPlayerDialog tpDialog = new TargetPlayerDialog();
            tpDialog.Presenter = Presenter;
            tpDialog.SelectTargets = true;
            if (tpDialog.ShowDialog() == true)
            {
                return tpDialog.TargetPlayerId;
            }
            else
            {
                return -1;
            }
        }

        public List<int> GetTargetPlayers()
        {
            TargetPlayerDialog tpDialog = new TargetPlayerDialog();
            tpDialog.SelectTargets = true;
            tpDialog.Presenter = Presenter;
            if (tpDialog.ShowDialog() == true)
            {
                return tpDialog.TargetPlayers;
            }
            else
            {
                return new List<int>();
            }
        }

        public void RaiseCommunicationsException(CommunicationExceptionEventArgs e)
        {
            //MessageBox.Show("There was an error communicating with the server. Game is terminating.\r\nError Details Follow\r\n" + e.InnerException.Message);
        }

        private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
        {
        	Presenter.Model.EndGame();
            Application.Current.Shutdown();
        }

        private void mnuMulligan_Click(object sender, System.Windows.RoutedEventArgs e)
        {
        	Presenter.Model.Mulligan();
        }

        private void mnuSaveLayout_Click(object sender, System.Windows.RoutedEventArgs e)
        {
            SaveLayout();
        }

        private void ReportIssue_Click(object sender, System.Windows.RoutedEventArgs e)
        {
            using (System.Diagnostics.Process process = new System.Diagnostics.Process())
            {
                process.StartInfo.FileName = "https://lapathy.fogbugz.com/default.asp?pg=pgPublicEdit";
                process.Start();
            }        	
        }

        public RandomCardParameters GetRandomRevealParameters()
        {
            TargetPlayerDialog tpDialog = new TargetPlayerDialog();
            tpDialog.RandomCards = true;
            tpDialog.SelectTargets = true;
            tpDialog.Presenter = Presenter;
            if (tpDialog.ShowDialog() == true)
            {
                return new RandomCardParameters()
                {
                    TargetPlayers = tpDialog.TargetPlayers,
                    Count = tpDialog.Count,
                    SourceZone = tpDialog.SourceZone
                };
            }
            else
            {
                return null;
            }        
        }

        public RandomCardParameters GetRandomDiscardParameters()
        {
            TargetPlayerDialog tpDialog = new TargetPlayerDialog();
            tpDialog.RandomCards = true;
            tpDialog.SelectTargets = false;
            tpDialog.Presenter = Presenter;

            if (tpDialog.ShowDialog() == true)
            {
                return new RandomCardParameters()
                {
                    TargetPlayers = tpDialog.TargetPlayers,
                    Count = tpDialog.Count,
                    SourceZone = tpDialog.SourceZone
                };
            }
            else
            {
                return null;
            }
        }

        private void Menu_RandomlyReveal(object sender, System.Windows.RoutedEventArgs e)
        {
            Presenter.Model.RandomReveal();
        }

        private void Menu_RandomlyDiscard(object sender, System.Windows.RoutedEventArgs e)
        {
            Presenter.Model.RandomDiscard();
        }
        #endregion
    }
}
